# 可下入深度计算
import math
from typing import List

from common.params import SoftParams
from model.soft.soft_common import AxialForceResult, data_init, UniForceResult
from model.soft.cable_fluid import get_cable_total_force
from model.soft.tool_fluid import get_tool_total_force

# 原来的液体阻力是计算完张力（取到最后的值）之后加上或减去液体阻力 现在改成计算轴力的过程中就要减去对应的其他流体阻力
# 其中电缆的其他流体阻力是在井底的电缆所受的阻力，电缆和仪器实际是固定不变的值，当做常量计算就行
# 仪器液体阻力均除以L1，正常上提下放的电缆液体阻力是除以D-L1的
# 计算 f 下放
def calc_f_push(D: float, params: SoftParams, cur: AxialForceResult, pre: AxialForceResult, preN: float,
                preF: float, is_Not_add_resistance: bool) -> float:
    factor_b: float = math.cos(math.radians(pre.inclination))
    tool_fluid: float = get_tool_total_force(params) / params.L1
    cable_fluid: float = get_cable_total_force(params) / (params.L_oh - params.L1)
    # 测井仪器的单位浮重
    w1: float = params.w1
    # 电缆的单位浮重
    w2: float = params.w2
    # 定义f
    f: float = 0.0
    params.L1 = round(params.L1)
    if is_Not_add_resistance == True:
        if (cur.depth >= D - params.L1) and (cur.depth < D):
            f: float = w1 * factor_b - params.get_mu_push(cur.depth) * preN + preF - tool_fluid
        elif (cur.depth > 0) and (cur.depth < D - params.L1):
            f: float = w2 * factor_b - params.get_mu_push(cur.depth) * preN + preF - cable_fluid
    else:
        if (cur.depth >= D - params.L1) and (cur.depth < D):
            f: float = w1 * factor_b - params.get_mu_push(cur.depth) * preN + preF
        elif (cur.depth > 0) and (cur.depth < D - params.L1):
            f: float = w2 * factor_b - params.get_mu_push(cur.depth) * preN + preF
    return f


# push 正压力计算
def calc_n_push(D: float, params: SoftParams, cur: AxialForceResult, F: float) -> float:
    # 测井仪器的单位浮重
    w1: float = params.w1
    # 电缆的单位浮重
    w2: float = params.w2
    params.L1 = round(params.L1)
    factor_a: float = cur.azimuth_rate
    factor_b: float = math.sin(math.radians(cur.inclination))
    factor_c: float = cur.inclination_rate
    if (cur.depth > D - params.L1) and (cur.depth <= D):
        factor_d: float = F * factor_a * factor_b
        factor_e: float = F * factor_c
        n: float = math.sqrt(math.pow(factor_d, 2) + math.pow(factor_e + w1 * factor_b, 2))
        return n
    elif (cur.depth > 0) and (cur.depth <= D - params.L1):
        factor_d: float = F * factor_a * factor_b
        factor_e: float = F * factor_c
        n: float = math.sqrt(math.pow(factor_d, 2) + math.pow(factor_e + w2 * factor_b, 2))
        return n


# cur 当前节点 d
# pre 上次迭代所计算的节点 d+1
# D 全井深
def calc_uni(D: float, params: SoftParams, cur: AxialForceResult, pre: AxialForceResult,
             _list_: List[AxialForceResult], is_Not_add_resistance: bool) -> AxialForceResult:
    # 几种类型的点
    cur.F_push = calc_f_push(D, params, cur, pre, pre.N_push, pre.F_push, is_Not_add_resistance)
    cur.N_push = calc_n_push(D, params, cur, cur.F_push)

    return cur


# 迭代函数
def deep_func(idx: int, input_depth: float, params: SoftParams, _list_: List[AxialForceResult], is_Not_add_resistance: bool) -> UniForceResult:
    # 本次迭代深度
    D: float = _list_[idx].depth
    params.L1 = round(params.L1)
    # 只有一种类型的点
    _list_[idx].F_push = 0.0
    _list_[idx].N_push = calc_n_push(D, params, _list_[idx], _list_[idx].F_push)

    result: UniForceResult = UniForceResult()
    # 下放时到达可下入极限深度
    push_cable_pressure = 0
    # 轴力开始小于0的点
    pressure_high_depth = 0
    # 轴力结束小于0的点
    pressure_low_depth = 0
    for i in range(idx - 1, -1, -1):

        _list_[i] = calc_uni(_list_[idx].depth, params, _list_[i], _list_[i + 1], _list_, is_Not_add_resistance)
        result.depth = D

        result.F_push = _list_[i].F_push
        result.N_push = _list_[i].N_push
        result.push_cable_pressure = 0
        result.pressure_high_depth = 0
        result.pressure_low_depth = 0
        # 如果轴力小于0  标记对应的点为1 即最大的极限下入深度 如果不受压则还是标记该点为 0 即还可以正常下入
        if (_list_[i].depth >= 0) and (_list_[i].depth < D - params.L1):
            # 原来是用result.F_push 由于要减掉液体阻力 现在使用原始的_list_[i].F_push
            # if result.F_push < 0.0:
            if _list_[i].F_push < 0.0:
                push_cable_pressure = 1
                if pressure_high_depth == 0:
                    pressure_high_depth = _list_[i].depth
                pressure_low_depth = _list_[i].depth  # 每次更新结束深度，直到找到满足条件的点
            if _list_[i].depth <= input_depth:
                result.N_push = _list_[i + 1].N_push
                result.push_cable_pressure = push_cable_pressure
                result.pressure_high_depth = pressure_high_depth
                result.pressure_low_depth = pressure_low_depth
                # print("==========={}==============".format(idx))
                # print("从深度{}开始迭代".format(_list_[idx].depth))
                # print(JsonUtil.obj2str(result))

                return result


# 聚合构建 返回计算结果
def uni_build(params: SoftParams, input_depth: float, _list_: List[AxialForceResult], is_Not_add_resistance: bool, desired_depths: List[float]) -> List[UniForceResult]:
    # T 为张力
    t: List[UniForceResult] = []
    # 设置迭代次数 判断当前深度是不是在间隔的列表里 如果在间隔列表里才进行迭代计算 否则不计算
    for depth in desired_depths:
        # 找到对应深度在 _list_ 中的索引
        idx = next((i for i, item in enumerate(_list_) if item.depth >= depth), None)
        if idx is not None and idx >= input_depth:
            # print("==========={}==============".format(idx))
            # print("从深度{}开始迭代".format(_list_[idx].depth))
            t_item: UniForceResult = deep_func(idx, input_depth, params, _list_, is_Not_add_resistance)
            # print(JsonUtil.obj2str(t_item))
            t.append(t_item)
    return t


def run(params: SoftParams,input_depth: float, _list_, is_Not_add_resistance: bool, desired_depths: List[float]) -> List[UniForceResult]:
    # 数据预处理
    result_arr: List[AxialForceResult] = data_init(_list_)
    # 计算结果
    result: List[UniForceResult] = uni_build(params, input_depth, result_arr, is_Not_add_resistance, desired_depths)

    return result
